package com.xinyu.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xinyu.config.NotificationProperties;
import com.xinyu.domain.Daily;
import com.xinyu.domain.Task;
import com.xinyu.domain.TaskStateHistory;
import com.xinyu.event.StatusChangeEvent;
import com.xinyu.notification.TaskStatusChangePublisher;
import com.xinyu.service.IComponentService;
import com.xinyu.service.IDailyService;
import com.xinyu.service.IEquipmentInfoService;
import com.xinyu.service.ITaskService;
import com.xinyu.service.IUserService;
import com.xinyu.service.TaskStateHistoryService;
import com.xinyu.utils.DateTimeUtils;
import com.xinyu.utils.JWTUtils;
import com.xinyu.utils.StatusLabelUtils;
import com.xinyu.vo.BaseResult;
import com.xinyu.vo.DailyRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author: XinYu
 * @since 2025-02-17
 */
@RestController
@RequestMapping("/daily")
public class DailyController {

    @Autowired
    private IDailyService dailyService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IEquipmentInfoService equipmentInfoService;

    @Autowired
    private IComponentService componentService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    @Autowired
    private NotificationProperties notificationProperties;

    @Autowired
    private ITaskService taskService;

    @Autowired
    private TaskStateHistoryService taskStateHistoryService;

    @Autowired
    private TaskStatusChangePublisher taskStatusChangePublisher;


    @PostMapping("/queryByCondition")
    public ResponseEntity<BaseResult> queryByCondition(@RequestBody DailyRequest dailyRequest){
        BaseResult br = dailyService.queryByCondition(dailyRequest);
        return ResponseEntity.ok(br);
    }

    @PostMapping("/save")
    public ResponseEntity<BaseResult> saveDailyLogWithAttachment(@RequestBody Daily daily) {
        LocalDateTime now = LocalDateTime.now();
        // 格式化时间（可选）
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = now.format(formatter);
        daily.setLogTime(formattedDateTime);

        daily.setHappendTime(DateTimeUtils.convertToMySQLDateTime(daily.getHappendTime()));

        daily.setTask(0);
        daily.setIsDelete(0);

        String token = request.getHeader("Authorization");
        Integer operatorId = JWTUtils.getUserIdFromToken(token);
        daily.setLogUserId(operatorId);

        dailyService.saveDailyWithAttachments(daily, operatorId);
        return ResponseEntity.ok(BaseResult.ok());
    }

    @PostMapping("/update")
    public ResponseEntity<BaseResult> updateDailyLogWithAttachment(@RequestBody Daily daily) {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedDateTime = now.format(formatter);
        daily.setUpdateTime(formattedDateTime);
        if (StringUtils.isNotBlank(daily.getHappendTime())) {
            daily.setHappendTime(DateTimeUtils.convertToMySQLDateTime(daily.getHappendTime()));
        }
        String token = request.getHeader("Authorization");
        Integer operatorId = JWTUtils.getUserIdFromToken(token);
        Daily previous = dailyService.getById(daily.getId());
        Task linkedTask = previous.getTaskId() == null ? null : taskService.getById(previous.getTaskId());
        Task previousTaskSnapshot = snapshotTask(linkedTask);
        dailyService.updateDailyWithAttachments(daily, operatorId);
        syncLinkedTaskStateIfNeeded(daily, previous, linkedTask, previousTaskSnapshot, operatorId, formattedDateTime);
        publishDailyStatusChangeEvent(daily, previous, operatorId);
        return ResponseEntity.ok(BaseResult.ok());
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<BaseResult> deleteById(@PathVariable Integer id) {
        Daily daily = dailyService.getById(id);
        daily.setIsDelete(1);

        boolean success = dailyService.updateById(daily);
        return ResponseEntity.ok(BaseResult.ok());
    }

    @GetMapping("/{id}")
    public ResponseEntity<BaseResult> findById(@PathVariable Integer id) {
        Daily daily = dailyService.findById(id);
        return ResponseEntity.ok(BaseResult.ok(daily));
    }

    @GetMapping("getDailyByTaskId/{taskId}")
    public ResponseEntity<BaseResult> getDailyByTaskId(@PathVariable Integer taskId) {
        LambdaQueryWrapper<Daily> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Daily::getTaskId, taskId); //
        List<Daily> dailyList = dailyService.list(queryWrapper);

        List<Daily> enrichedList = dailyList.stream()
                .map(daily -> {
                    Daily detail = dailyService.findById(daily.getId());
                    detail.setUser(userService.getById(daily.getLogUserId()));
                    detail.setEquipment(equipmentInfoService.getById(daily.getEquipmentId()));
                    detail.setComponent(componentService.getById(daily.getComponentId()));
                    return detail;
                })
                .collect(java.util.stream.Collectors.toList());
        return ResponseEntity.ok(BaseResult.ok(enrichedList));
}

    private void publishDailyStatusChangeEvent(Daily updated, Daily previous, Integer operatorId) {
        if (previous == null) {
            return;
        }
        if (Objects.equals(previous.getState(), updated.getState())) {
            return;
        }
        Set<Integer> recipients = new LinkedHashSet<>();
        if (previous.getLogUserId() != null) {
            recipients.add(previous.getLogUserId());
        }
        if (updated.getLogUserId() != null) {
            recipients.add(updated.getLogUserId());
        }
        Task linkedTask = previous.getTaskId() == null ? null : taskService.getById(previous.getTaskId());
        if (linkedTask != null) {
            if (linkedTask.getPublishUserId() != null) {
                recipients.add(linkedTask.getPublishUserId());
            }
            if (linkedTask.getResponsibleUserId() != null) {
                recipients.add(linkedTask.getResponsibleUserId());
            }
        }
        List<Integer> recipientList = new ArrayList<>(recipients);
        if (recipientList.isEmpty()) {
            return;
        }
        StatusChangeEvent event = new StatusChangeEvent(
                StatusChangeEvent.EntityType.DAILY,
                updated.getId(),
                StringUtils.defaultIfBlank(updated.getTitle(), previous.getTitle()),
                previous.getState(),
                updated.getState(),
                StatusLabelUtils.dailyStateLabel(updated.getState()),
                StringUtils.defaultIfBlank(updated.getDescription(), "状态已更新"),
                operatorId,
                recipientList,
                notificationProperties.buildDailyDetailUrl(updated.getId()),
                true,
                false,
                null,
                null
        );
        eventPublisher.publishEvent(event);
    }

    private void syncLinkedTaskStateIfNeeded(Daily updatedDaily,
                                             Daily previousDaily,
                                             Task linkedTask,
                                             Task previousTaskSnapshot,
                                             Integer operatorId,
                                             String timestamp) {
        if (linkedTask == null || previousTaskSnapshot == null) {
            return;
        }
        Integer newState = updatedDaily.getState();
        if (newState == null || Objects.equals(previousTaskSnapshot.getState(), newState)) {
            return;
        }
        String reason = String.format("问题%d状态同步为%s",
                updatedDaily.getId(),
                StatusLabelUtils.dailyStateLabel(newState));
        linkedTask.setState(newState);
        linkedTask.setStateReason(reason);
        if (newState == 3 || newState == 4) {
            linkedTask.setCompletedTime(timestamp);
        }
        taskService.updateById(linkedTask);
        taskStateHistoryService.save(new TaskStateHistory(linkedTask.getId(), newState, reason, operatorId, timestamp));
        taskStatusChangePublisher.publish(linkedTask, previousTaskSnapshot, previousDaily, operatorId, reason);
    }

    private Task snapshotTask(Task task) {
        if (task == null) {
            return null;
        }
        Task snapshot = new Task();
        snapshot.setId(task.getId());
        snapshot.setState(task.getState());
        snapshot.setResponsibleUserId(task.getResponsibleUserId());
        snapshot.setPublishUserId(task.getPublishUserId());
        snapshot.setTitle(task.getTitle());
        return snapshot;
    }
}

